/************************************************************
 * Copyright (c) 2010 Georg Fritzsche
 *
 * This project is licensed under the "New BSD License": 
 * http://www.opensource.org/licenses/bsd-license.php
 ***********************************************************/

#ifndef TRIGGER_MIDI_LISTENER_H
#define TRIGGER_MIDI_LISTENER_H

#include <functional>
#include <stdexcept>
#include <vector>
#include <map>
#include <boost/integer_traits.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <boost/cstdint.hpp>

class Config;
class Player;
class RtMidiIn;

struct midi_error : std::runtime_error 
{
    midi_error(const std::string& message) throw() : std::runtime_error(message) {}
};

class MidiListener
{
public:
    enum Action
    {
        ActionNext,
        ActionReset
    };
    
public:
    MidiListener(const boost::shared_ptr<Player>& player, const Config& config);
    ~MidiListener();

    static const unsigned invalid_port = boost::integer_traits<unsigned>::const_max;
    
    static void listPorts();

public:
    typedef std::vector<unsigned char> Message;
    typedef boost::function<void (Player*)> Command;
    typedef std::map<Message, Command, bool (*)(const Message& a, const Message& b)> CommandMap;
    typedef std::map<Action, Message> ActionMap;
    
private:
    static void midi_callback(double deltatime, std::vector<unsigned char>* message, void* userData);
    void execute(const Message& msg);

    boost::shared_ptr<Player> m_player;
    boost::shared_ptr<RtMidiIn> m_midiIn;
    const CommandMap m_commandMap;
};

#endif
